package com.jusfoun.communication.controller;

import com.jusfoun.communication.model.Message;
import com.jusfoun.communication.model.User;
import com.jusfoun.communication.service.ManageService;
import com.jusfoun.communication.service.MessageService;
import com.jusfoun.communication.service.UserService;
import com.jusfoun.communication.util.PageInfo;
import com.jusfoun.communication.util.Result;
import com.jusfoun.communication.util.ResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 消息相关的controller
 *
 * @author player six
 * @email jslcylcy@163.com
 * @create 2017-10-13 17:06
 **/
@RestController
@RequestMapping("/message")
@CrossOrigin
@Api(description = "消息管理接口")
public class MessageController {
    private static final Logger logger = LoggerFactory.getLogger(MessageController.class);

    @Autowired
    private ResultUtil resultUtil;

    @Autowired
    private MessageService messageService;

    @Autowired
    private ManageService manageService;

    @Autowired
    private UserService userService;

    @Value("${file.uploadPath}")
    private String uploadPath;

    @Value("${file.downloadPath}")
    private String downloadPath;

    /**
     * api发送消息
     *
     * @param message
     * @return
     */
    @ApiOperation(value = "发送消息", notes = "将消息发送到指定用户或者用户组<br> code类型 <br>" +
            "100:App内普通用户一对一消息<br>101:App向用户发送的一对一消息<br>102:App向所有用户发送的消息<br>103:App向指定group发送的消息" +
            "<br>104:App向指定tag发送的消息<br>105:App内普通用户一对一消息(如果设置自动回复,会触发自动消息回复)<br>" +
            "106:系统自动回复的消息<br>200:心跳消息<br>300:websocket消息格式错误<br>301:Websocket消息格式错误,缺少发送对象" +
            "<br>302:未能识别的code,非法code<br>400:用户重复登录被踢出之前系统向用户发送的消息")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "appId", value = "appId", required = true, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "appSecret", value = "appSecret", required = true, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "to", value = "消息接收方", required = false, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "from", value = "消息发送方", required = false, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "text", value = "消息内容", required = false, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "type", value = "消息类型,默认text", required = false, paramType = "form", dataType = "String", allowableValues = "text,image,video,audio,file"),
                    @ApiImplicitParam(name = "code", value = "消息类型code", required = true, paramType = "form", dataType = "int"
                            , allowableValues = "100,101,102,103,104,105"),
            }
    )
    @RequestMapping(value = "/sendMsg", method = RequestMethod.POST)
    public Result sendMsg(@ApiIgnore Message message) {
        logger.info("后台api接口发送消息:" + message.getAppId() + ",code:" + message.getCode() + ",user1:" + message.getTo() + ",user2:" + message.getFrom());
        if (checkUser(message)) {
            return resultUtil.fail("失败", "鉴权失败");
        }
        return messageService.dealSendMsg(message);
    }

    private boolean checkUser(@ApiIgnore Message message) {
        if (StringUtils.isEmpty(message.getToken()) && (StringUtils.isBlank(message.getAppId()) || StringUtils.isBlank(message.getAppSecret()))) {
            logger.info("token,appId与appSecret为空");
            return true;
        }
        if (StringUtils.isNotBlank(message.getToken())) {
            User user = userService.checkWebSocketConn(message.getToken());
            if (user == null) {
                logger.info("鉴权失败:" + message.getToken());
                return true;
            }
            message.setAppId(user.getAppId());
            message.setFrom(user.getUserName());
        } else {
            if (!manageService.checkAppIdAndSecret(message.getAppId(), message.getAppSecret())) {
                logger.info("appId与appSecret不匹配");
                return true;
            }
        }
        return false;
    }

    /**
     * 文件类型消息接口
     *
     * @return
     */

    @ApiOperation(value = "发送文件消息", notes = "将消息发送到指定用户或者用户组<br> code类型 <br>" +
            "100:App内普通用户一对一消息<br>101:App向用户发送的一对一消息<br>102:App向所有用户发送的消息<br>103:App向指定group发送的消息" +
            "<br>104:App向指定tag发送的消息<br>105:App内普通用户一对一消息(如果设置自动回复,会触发自动消息回复)<br>" +
            "106:系统自动回复的消息<br>200:心跳消息<br>300:websocket消息格式错误<br>301:Websocket消息格式错误,缺少发送对象" +
            "<br>302:未能识别的code,非法code<br>400:用户重复登录被踢出之前系统向用户发送的消息")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "appId", value = "appId，需与appSecret同时存在", required = false, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "appSecret", value = "appSecret", required = false, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "token", value = "token，token，appId与appSecret必须存在一个", required = false, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "to", value = "消息接收方", required = false, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "from", value = "消息发送方", required = false, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "text", value = "消息内容", required = false, paramType = "form", dataType = "String"),
                    @ApiImplicitParam(name = "type", value = "消息类型,默认text", required = false, paramType = "form", dataType = "String", allowableValues = "text,image,video,audio,file"),
                    @ApiImplicitParam(name = "code", value = "消息类型code", required = true, paramType = "form", dataType = "int"
                            , allowableValues = "100,101,102,103,104,105"),
                    @ApiImplicitParam(name = "files[]", value = "文件，可以传输多个", required = false, paramType = "form", dataType = "file数组"),
            }
    )
    @RequestMapping(value = "/sendMsg-file", method = RequestMethod.POST)
    public Result sendFileMsg(@ApiIgnore Message message, @RequestParam("files[]") MultipartFile[] files) throws IOException {
        logger.info("后台api接口发送文件消息:" + message.getAppId() + ",code:" + message.getCode() + ",user1:" + message.getTo() + ",user2:" + message.getFrom());
        if (checkUser(message)) {
            return resultUtil.fail("失败", "鉴权失败");
        }
        if (StringUtils.isEmpty(message.getType())) {
            return resultUtil.fail("失败", "type不能为空");
        }
        message.setTime(new Date());
        List<Message.File> fileList = new ArrayList<>();
        for (MultipartFile file : files) {
            String fileName = UUID.randomUUID().toString() + getSuffixName(file.getOriginalFilename());
            File newFile = new File(uploadPath + fileName);
            FileUtils.copyInputStreamToFile(file.getInputStream(), newFile);
            Message.File f = new Message.File(downloadPath + fileName, file.getOriginalFilename());
            fileList.add(f);
        }
        message.setFileList(fileList);
        return messageService.dealSendMsg(message);
    }

    /**
     * 查询某两个用户之间的聊天记录
     *
     * @param message
     * @return
     */
    @ApiOperation(value = "查询两个用户之间的历史消息", notes = "查询两个用户之间的历史消息<br> code类型 <br>" +
            "100:App内普通用户一对一消息<br>101:App向用户发送的一对一消息<br>102:App向所有用户发送的消息<br>103:App向指定group发送的消息" +
            "<br>104:App向指定tag发送的消息<br>105:App内普通用户一对一消息(如果设置自动回复,会触发自动消息回复)<br>" +
            "106:系统自动回复的消息<br>200:心跳消息<br>300:websocket消息格式错误<br>301:Websocket消息格式错误,缺少发送对象" +
            "<br>302:未能识别的code,非法code" +
            "<br>400:用户重复登录被踢出之前系统向用户发送的消息")
    @RequestMapping(value = "/history", method = RequestMethod.GET)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "appId", value = "appId", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "appSecret", value = "appSecret", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "to", value = "消息接受方", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "from", value = "消息发送方", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "页码", required = false, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页数量", required = false, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "scanIndexForward", value = "正序或者逆序", required = false, dataType = "boolean", paramType = "query"),
    }
    )
    public PageInfo<Message> historyMsg(@ApiIgnore Message message, Integer pageNum, Integer pageSize, @RequestParam(required = false, defaultValue = "false") Boolean scanIndexForward) {
        logger.info("获取用户间消息记录,appId:" + message.getAppId() + ",user1:" + message.getTo() + ",user2:" + message.getFrom());
        if (StringUtils.isBlank(message.getAppId()) || StringUtils.isBlank(message.getAppSecret()) || StringUtils.isBlank(message.getTo()) || StringUtils.isBlank(message.getFrom())) {
            logger.info("参数不合法");
            return new PageInfo<>();
        }
        if (!manageService.checkAppIdAndSecret(message.getAppId(), message.getAppSecret())) {
            logger.info("appId与appSecret不匹配");
            return new PageInfo<>();
        }
        return messageService.historyMsg(message, pageNum, pageSize, scanIndexForward);
    }

    /**
     * 查询用户消息记录
     *
     * @param user
     * @return
     */
    @ApiOperation(value = "查询用户的历史消息", notes = "查询用户的历史消息<br> code类型 <br>" +
            "100:App内普通用户一对一消息<br>101:App向用户发送的一对一消息<br>102:App向所有用户发送的消息<br>103:App向指定group发送的消息" +
            "<br>104:App向指定tag发送的消息<br>105:App内普通用户一对一消息(如果设置自动回复,会触发自动消息回复)<br>" +
            "106:系统自动回复的消息<br>200:心跳消息<br>300:websocket消息格式错误<br>301:Websocket消息格式错误,缺少发送对象" +
            "<br>302:未能识别的code,非法code" +
            "<br>400:用户重复登录被踢出之前系统向用户发送的消息")
    @RequestMapping(value = "/history-all", method = RequestMethod.GET)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "appId", value = "appId", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "appSecret", value = "appSecret", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "userName", value = "用户名称", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "页码", required = false, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页数量", required = false, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "scanIndexForward", value = "正序或者逆序", required = false, dataType = "boolean", paramType = "query"),
            @ApiImplicitParam(name = "beginTime", value = "最小时间,yyyyMMddHHmmss", required = false, dataType = "datetime", paramType = "query"),
            @ApiImplicitParam(name = "endTime", value = "最大时间,yyyyMMddHHmmss", required = false, dataType = "datetime", paramType = "query"),
    }
    )
    public PageInfo<Message> historyMsg(@ApiIgnore User user, Integer pageNum, Integer pageSize, @RequestParam(required = false, defaultValue = "false") Boolean scanIndexForward
            , @RequestParam(required = false) String beginTime, @RequestParam(required = false) String endTime) {
        logger.info("获取用户消息记录,appId:" + user.getAppId() + ",user:" + user.getUserName());
        if (StringUtils.isBlank(user.getAppId()) || StringUtils.isBlank(user.getAppSecret()) || StringUtils.isBlank(user.getUserName())) {
            logger.info("参数不合法");
            return new PageInfo<>();
        }
        if (!manageService.checkAppIdAndSecret(user.getAppId(), user.getAppSecret())) {
            logger.info("appId与appSecret不匹配");
            return new PageInfo<>();
        }
        return messageService.listMessage(user.getAppId(), user.getUserName(), pageNum, pageSize, scanIndexForward, beginTime, endTime);
    }

    /**
     * 获取后缀名称
     *
     * @param filename
     * @return
     */
    private String getSuffixName(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length()))) {
                return filename.substring(dot, filename.length());
            }
        }
        return null;
    }

}
